home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / softwareupdate / system / amigados / files / files.doc < prev    next >
Text File  |  1996-10-10  |  41KB  |  1,096 lines

  1. 2    FILES
  2.  
  3. 2.1  INTRODUCTION
  4.  
  5. In this chapter I will explain how to work with files. I will
  6. describe how you open files, read as well as save data, and
  7. finally close the file again. In this chapter I will also
  8. explain how to work with files in a multitasking environment.
  9.  
  10. I will concentrate this chapter to only discuss the most
  11. commonly used file functions. In the follwoing chapters you will
  12. find more advanced routines like the "buffered IO" as well as
  13. other types of useful function which you might need.
  14.  
  15.  
  16.  
  17. 2.2  SOME GENERAL INFORMATION ABOUT FILES
  18.  
  19. If you have not worked with files before you might feel a bit
  20. confused when you hear someone mention "file cursors" and
  21. "exclusive locks" and so forth... However, do not dispair, I
  22. will try to do my best to explain these things.
  23.  
  24. A "file" is simply a collection of data which have been stored,
  25. and can later be retreived (read). Data can be stored on many
  26. types of devices, but the most commonly used place to store
  27. data is oundouptedly on a disk. Data can also be stored on
  28. tapes, hard disks, laser disks, and so on...
  29.  
  30. A program can create a new file and store data in it, or it can
  31. collect data from an already existing file. A program can also
  32. append new data or alter data in an existing file.
  33.  
  34. When you want to use a file you first have to "open" it. When
  35. you open a file AmigaDOS prepares the system and the file so
  36. they can start to send and receive data.
  37.  
  38. AmigaDOS is using a "file cursor" which is like a pointer that
  39. can be moved around inside the file like the pickup of a record
  40. player. When you open a file the file cursor is always
  41. positioned at the beginning of the file. Since all data in a
  42. file are treated as bytes will the file cursor simply point to
  43. the first byte in the file.
  44.  
  45. See picture "ReadWrite.pic". At the top of the picture you can
  46. see a long rectangle filled with question marks. This is how
  47. an empty disk may be illustrated. Since the disk is empty we
  48. do not know what values are stored on it, if there are any, 
  49. therefore the question marks.
  50.  
  51.   1. When we "open" the file (with help of the Open() function
  52.      which will be explained later on) the file cursor is
  53.      positioned at the beginning of the file, here illustrated
  54.      as a small arrow. You can see that the file cursor points
  55.      to the first byte in the file.
  56.  
  57.   2. We then write some data to the file (with help of the
  58.      Write() function which will soon be explained). We send
  59.      the text "HELLO", and it will be stored in the file.
  60.      Remember that a file is like an array of bytes, and
  61.      consequently each letter is stored in a byte. A letter
  62.      (char) is treated as a byte by C, and you could
  63.      therefore equally well have sent the numbers 72, 69, 76,
  64.      76 and 79 which are the ASCII values of "HELLO".
  65.  
  66.      When you send data to a file there is sometimes put a
  67.      a special "End Of File" sign at the end of the file. This
  68.      "EOF" sing (the constant "EOF" is defined as -1 in header
  69.      file "stdio.h") is used by some of the standard routines
  70.      in C, but actually NOT used by AmigaDOS. (AmigaDOS uses
  71.      instead some other routines to keep track of the file
  72.      length, but this will not be discussed here.)
  73.      
  74.      However, although AmigaDOS does not use the EOF sign I
  75.      have included it in the picture since the file routines
  76.      acts like if there was a sign at the end of the file. The
  77.      EOF sign simply illustrates the end of the file although
  78.      it acutally is unknown byte as the following question
  79.      marks.
  80.      
  81.      As you can see on the picture the text "HELLO" has been
  82.      stored in the file, one character (or byte if you so like)
  83.      in each box after each other. You can also see that the
  84.      file cursor now has moved and is pointing at the end of
  85.      the file, ready to add more data if necessary.
  86.  
  87.   3. We now sends some data to the file again, and the text
  88.      " WORLD" is appended to the file. The file cursor is once
  89.      again moved to the end of the file ready to append even
  90.      more data.
  91.  
  92.   4. If we now would like to read some of the data we have
  93.      stored we must first move the file cursor back to the
  94.      first character (byte) we want to read. (We move the file
  95.      cursor with help of the Seek() function which will as all
  96.      the other functions be explained in the following
  97.      sections. Here we tell AmigaDOS to move the file curser
  98.      three bytes foreward from the beginning of the file.)
  99.  
  100.   5. We now read some data (with help of the Read() function)
  101.      which we have previously stored. In this example we read
  102.      seven characters (bytes) from the current position and
  103.      consequently we get the text "LO WORLD".
  104.      
  105.   6. When you do not want to use the file any more you have to
  106.      "close" it so other programs can read and or modify it
  107.      later on. (To close a file you use the Close() function.)
  108.      The file cursor will then automatically be removed.
  109.  
  110.  
  111.  
  112. 2.3  WORK WITH FILES
  113.  
  114. The procedure of working with files is relative simple. First
  115. you have to declare a BCPL pointer (A BPTR) which you have to
  116. use whenever you want to do something with the file.
  117.  
  118.   /* A "BCPL" pointer to our file: */
  119.   BPTR my_file;
  120.  
  121.  
  122. You should the "open" the file which will prepare the system so
  123. later can use the file. To open files you use the "Open()"
  124. function. Once you have opened the file you can start to read
  125. data with help of the "Read()" function, write data with help
  126. of the "Write()" function, as well as move the file cursor with
  127. help of the "Seek()" function. When you do not want to use the
  128. file any more you close it by calling the "Close()" function.
  129.  
  130. Sometimes when you have received an error you can call a
  131. special function named "IoErr()" which will give you some more
  132. information about the error. This function is, however, first
  133. explained in chapter 8 "Miscellaneous" so you do not have to
  134. bother about it yet.
  135.  
  136.  
  137.  
  138. 2.3.1  OPEN THE FILE
  139.  
  140. Before you can do anything with a file you have to ask AmigaDOS
  141. to "open" it. When you open a file you actualy tell the
  142. computer what you would like to do with the file. You might
  143. want to open a new file or an already existing one.
  144.  
  145. When you tell AmigaDOS that you want to open an old file the
  146. file cursor will be positioned in the beginning of the old
  147. file, pointing to the first byte. You can also open a file as
  148. "new", and a new file will be created for you and the file
  149. cursor is positioned in the beginning of the new file. If you
  150. open an already existing file as a "new" file the existing file
  151. will be deleted and a new one created for you.
  152.  
  153. To open files you should use the Open() function:
  154.  
  155. ---------------------------------------------------------------
  156.  
  157. Open()
  158.  
  159. ROM library: "dos.library/Open", (All Versions)
  160. #include <clib/dos_protos.h>
  161.  
  162. Opens a new or old file for input and/or output, and puts a
  163. "read" or "write" lock on the file.
  164.  
  165. Synopsis:    my_file = Open( file_name, mode );
  166.  
  167.   my_file:   (BPTR) If the file could be opened a BPTR (BPCL
  168.              pointer) is returned. If the file on the other
  169.              hand could not be opened NULL is returned.
  170.  
  171.   file_name: (STRPTR) Pointer to a text string which contains
  172.              the name of the file you want to open. If the file
  173.              is not located in the current directory you have
  174.              to include any necessary device/directory names.
  175.              (The device/directory part is usually reffered as
  176.              the "path", and tells AmigaDOS where the file can
  177.              be found.)
  178.  
  179.   mode:      (LONG) When you want to open a file you must tell
  180.              AmigaDOS how you want to open the file. For the
  181.              mement there exist three modes: (The flags are
  182.              defined in header file "dos/dos.h")
  183.  
  184.              MODE_OLDFILE:   Opens an existing file for reading
  185.                              and writing. The file will be
  186.                              "locked" so other programs can read
  187.                              it but not modify it before you
  188.                              have "un-locked" the file. This is
  189.                              usually called a "write lock"
  190.                              ("shared lock"). 
  191.  
  192.                              If the file does not exist or it
  193.                              is used by some other program
  194.                              ("read or write locked") Open()
  195.                              will fail and NULL is returned.
  196.  
  197.              MODE_NEWFILE:   Opens a new file for writing. If
  198.                              the file already exist it will be
  199.                              deleted so a new file with the
  200.                              same name can be created.
  201.                              
  202.                              Note that the data in an existing
  203.                              file will be deleted if you use
  204.                              this flag on an already existing
  205.                              file! Be careful so you do not
  206.                              destroy important data!
  207.  
  208.                              The file will be "locked" so no
  209.                              other programs can read nor write
  210.                              to it. This is usually called a
  211.                              "read/write lock" ("exclusive
  212.                              lock")
  213.                              
  214.                              If the file already exist and is
  215.                              used by some other program ("read
  216.                              or write locked") Open() will fail
  217.                              and NULL is returned.
  218.                              
  219.              MODE_READWRITE: Opens an old file as described
  220.                              with the "MODE_OLDFILE" flag.
  221.                              However, if the file does not
  222.                              exist it will be created.
  223.                              
  224.                              If the file is used by some other
  225.                              program ("read or write locked")
  226.                              Open() will fail and NULL is
  227.                              returned.
  228.                           
  229.              Regardless of what mode you chose the file cursor
  230.              will always be positioned in the beginning of the
  231.              file if it could be opened. (The file cursor will
  232.              point to the first byte/character in the file).
  233.  
  234. You may of course have as many files open at the same time as
  235. you want. Note that each file you have opened has its own file
  236. cursor. When you work with one file you do not have to bother
  237. about the other ones. If you move around inside one file the
  238. others files' file cursors will remain unmodified. Of course 
  239. you need a BPTR for each file, and you have to open each file
  240. separately.
  241.  
  242. Here is a simple example on how to use the Open() function:
  243.  
  244.   /* A "BCPL" pointer to our file: */
  245.   BPTR my_file;
  246.  
  247.   - - -
  248.  
  249.   /* Try to open a file as "new": */
  250.   my_file = Open( "Highscore.dat", MODE_NEWFILE );
  251.  
  252.   /* Check if we have successfully opened the file or not: */
  253.   if( my_file == NULL )
  254.     printf( "Could not open the file!\n" );
  255.  
  256.  
  257. See also: Close(), IoErr(), Lock(), OpenFromLock(), Read(),
  258.           Seek(), UnLock(), Write()
  259.  
  260. ---------------------------------------------------------------
  261.  
  262.  
  263.  
  264. 2.3.2  READ DATA
  265.  
  266. Once you have successfully opened a file you can start to read
  267. from it or write to it. AmigaDOS consider files to be a stream
  268. of bytes, and every time you read a file you have to specify
  269. how many bytes you want to read. To read a single character you
  270. should read 1 byte since the size of a character is exactly one
  271. byte. To read an integer you have to read 4 bytes, and so on...
  272.  
  273. Since you most of the time want to read complete structures or
  274. arays of data it can be rather difficult to calculate the right
  275. number of bytes if you have to do it yourself. Luckily there
  276. exist a small function in C called "sizeof()" which simply
  277. returns the size in bytes of a specified object:
  278.  
  279.   Synopsis: size = sizeof( object );
  280.   
  281.       size: The size of the specified object (in bytes).
  282.  
  283.     object: The object you want to know the size of.
  284.  
  285. Example:
  286.  
  287.   /* Get the size (in bytes) of an object: */
  288.   struct Screen my_screen;
  289.   size = sizeof( struct Screen );
  290.  
  291.  
  292. If you want to get the size of a string you should use another
  293. standard C function called "strlen()":
  294.  
  295.   Synopsis: length = strlen( string );
  296.   
  297.     length: The number of characters in the string. (Remember
  298.             that one character is equal to one byte.)
  299.     
  300.     string: Pointer to a NULL terminated string you want to
  301.             examine.
  302.  
  303. Example:
  304.  
  305.   /* Get the length (number of characters) in a string: */
  306.   UBYTE my_string = "The Amiga C Encyclopedia!";
  307.   length = strlen( my_string );
  308.  
  309.  
  310. To read some bytes in a file you can use the Read() function.
  311. It will collect a specified number of bytes starting from the
  312. current position of the file cursor. The Read() function is
  313. defined like this:
  314.  
  315. ---------------------------------------------------------------
  316.  
  317. Read()
  318.  
  319. ROM library: "dos.library/Read", (All Versions)
  320. #include <clib/dos_protos.h>
  321.  
  322. Reads a specified number of bytes in a file.
  323.  
  324. Synopsis: count = Read( file, buffer, size );
  325.  
  326.   count:  (LONG) The function returns the number of bytes
  327.           actually read. When you tell AmigaDOS that you want
  328.           to read X number of bytes it is not certain that you
  329.           actually can do it. The file might be shorter than
  330.           you expected or the file might be corrupted, etc...
  331.  
  332.           The returned value can be:
  333.              
  334.              1. equal to the number of bytes requested. In this
  335.              case everything went as expected. The requested
  336.              number of bytes were read, and there were no
  337.              errors.
  338.              
  339.              2. equal to -1. In this case there was an error
  340.              while the function tried to read the data. How
  341.              much, if any, data were actually read before the
  342.              error occured is imposible to say, and you should
  343.              not use the values in the buffer. If you receive
  344.              this value you may call IoErr() to get more
  345.              information about the error.
  346.  
  347.              3. less than the number of bytes requested, but
  348.              not equal to -1. In this case we have simply
  349.              reached the end of the file, and there was no
  350.              error. 
  351.              
  352.              Please note that reaching the end of the file
  353.              before expected can sometimes indicate that there
  354.              was some sort of error. If you have saved for
  355.              example 10 structures of a certain size, and when
  356.              you later tries to read the file and only get four
  357.              structures there is obviously something wrong. It
  358.              is, however, not a dos error and the file itself
  359.              is ok. It is the data in the file which is
  360.              incorrect, but that is not AmigaDOS's fault.
  361.              
  362.   file:   (BPTR) A BCPL pointer to an already open file.
  363.  
  364.   buffer: (APTR) Pointer to some memory where the collected
  365.           data can be stored.
  366.  
  367.   size:   (LONG) Number of bytes you want to read.
  368.  
  369.  
  370. Note! The function does not check that the buffer you give it
  371. is big enough to store all values you requested! You may never
  372. try to read more bytes than can fit in your buffer!
  373.  
  374. Here is a simple example on how to use the Read() function:
  375.  
  376.   /* Some memory where we will store the collected data: */
  377.   int my_highscore[ 10 ];
  378.  
  379.   /* The number of bytes actually collected: */
  380.   long bytes_read;
  381.  
  382.   - - -
  383.  
  384.   /* Read some data from an already open file: */
  385.   bytes_read = Read( my_file, my_highscore, sizeof( my_highscore ) );
  386.  
  387.   /* Did we get all data? */ 
  388.   if( bytes_read != sizeof( my_highscore ) )
  389.   {
  390.     /* No! We could not read all values! */
  391.     printf( "Error! Could read all values!\n" );
  392.   }
  393.   else
  394.   {
  395.     /* Yes! All recuested data were successfully collected! */
  396.     printf( "Data collected!\n" );
  397.   }
  398.  
  399.  
  400. See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
  401.           Seek(), UnLock(), Write()
  402.  
  403. ---------------------------------------------------------------
  404.  
  405.  
  406.  
  407. 2.3.3  WRITE DATA
  408.  
  409. To write some data (bytes) to a file you can use the Write()
  410. function. It will write a specified number of bytes starting
  411. from the current position of the file cursor. The Write()
  412. function is defined like this:
  413.  
  414. ---------------------------------------------------------------
  415.  
  416. Write()
  417.  
  418. ROM library: "dos.library/Write", (All Versions)
  419. #include <clib/dos_protos.h>
  420.  
  421. Writes a specified number of bytes to a file.
  422.  
  423. Synopsis: count = Write( file, buffer, size );
  424.  
  425.   count:  (LONG) The function returns the number of bytes
  426.           actually written. When you tell AmigaDOS that you want
  427.           to write X number of bytes it is not certain that you
  428.           actually can do it. The file is maybe write protected,
  429.           or the disk is full etc...
  430.  
  431.           The returned value can be:
  432.              
  433.              1. equal to the number of bytes requested. In this
  434.              case everything went as expected. The requested
  435.              number of bytes were written, and there were no
  436.              errors.
  437.              
  438.              2. equal to -1. In this case there was an error
  439.              while the function tried to write the data. No
  440.              data will have been saved. If you receive this
  441.              value you may call IoErr() to get more information
  442.              about the error.
  443.  
  444.              3. less than the number of bytes requested, but
  445.              not equal to -1. In this case the operation was
  446.              aborted because of some external event (disk full
  447.              etc...), and the value returned tells us how many
  448.              bytes that have been saved.
  449.              
  450.              If you could not save all the data you should
  451.              in most situations remove the half filled file
  452.              (it is probably useless if not all data could
  453.              be saved) and ask the user to for example insert
  454.              a new disk etc... depending on what have happened.
  455.              
  456.              Do NOT just tell the user that there was a problem
  457.              and then quit! (In small examples and if the data
  458.              is unimportant this is of course OK, but bigger
  459.              applications should try to solve the problem.)
  460.              
  461.   file:   (BPTR) A BCPL pointer to an already open file.
  462.  
  463.   buffer: (APTR) Pointer to some memory where the data that
  464.           should be written (saved) are stored.
  465.  
  466.   size:   (LONG) Number of bytes you want to write.
  467.  
  468.  
  469. Here is a simple example on how to use the Write() function:
  470.  
  471.   /* Some data we want to save: */
  472.   int my_highscore[ 10 ] =
  473.     { 34, 76, 328, 723, 1027, 1201, 1416, 2645, 3050, 3876 };
  474.  
  475.   /* The number of bytes actually written: */
  476.   long bytes_written;
  477.  
  478.   - - -
  479.  
  480.   /* Write some data to a file: */
  481.   bytes_written = Write( my_file, my_highscore, sizeof( my_highscore ) );
  482.  
  483.   /* Did we write all data? */ 
  484.   if( bytes_written != sizeof( my_highscore ) )
  485.   {
  486.     /* No! We could not write (save) all data! */
  487.     printf( "Error! Could not save all values!\n" );
  488.   }
  489.   else
  490.   {
  491.     /* Yes, all numbers have been written to the file! */
  492.     printf( "All values were saved successfully!\n" );
  493.   }
  494.  
  495.   
  496. See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
  497.           Read(), Seek(), UnLock()
  498.  
  499. ---------------------------------------------------------------
  500.  
  501.  
  502.  
  503. 2.3.4  MOVE INSIDE A FILE
  504.  
  505. The Read() and Write() functions will start their operations at
  506. the byte which the file cursor is currently pointing to. When
  507. you open a file the file curser is positioned at the beginning
  508. of the file. This may of course not be the position you desire.
  509.  
  510. If you, for example, want add data to the file you need to move
  511. the file cursor to the end of the file. If you on the other
  512. hand have just written some data to a file and would like to
  513. read it again you have to move the file cursor back to the
  514. positon you want to start to read at.
  515.  
  516. To move the file cursor you should use the "Seek()" function.
  517. You tell it which position you want to move to. The position is
  518. relative to a specified "offest position" which can either be
  519. the beginning of the file, the current position, or the end of
  520. the file. (See picture "OffsetPosition.pic")
  521.  
  522. The Seek() function is defined like this:
  523.  
  524. ---------------------------------------------------------------
  525.  
  526. Seek()
  527.  
  528. ROM library: "dos.library/Seek", (All Versions)
  529. #include <clib/dos_protos.h>
  530.  
  531. Moves the file cursor to a specified position in a file.
  532.  
  533. Synopsis:   old_pos = Seek( file, position, offset );
  534.  
  535.   old_pos:  (LONG) The function returns the previous position
  536.             in the file, or -1 if there was an error and the
  537.             file cursor could not be moved. If there was an
  538.             error you should of course not try to read or
  539.             write any data until the problem has been solved
  540.             and you have successfully positioned the file
  541.             cursor.
  542.             
  543.             If there is an error you should call IoErr() to
  544.             get more information about the error.
  545.  
  546.   file:     (BPTR) A BCPL pointer to an already open file.
  547.  
  548.   position: (LONG) The position you want to move the file
  549.             cursor to. Note that this value is an relative
  550.             to the specified "offset position".
  551.  
  552.   offest:   (LONG) The specified position is relative to one
  553.             one of these "offset positions": (The flags are
  554.             defined in header file "dos/dos.h")
  555.  
  556.                OFFSET_BEGINNING: Beginning of the file.
  557.  
  558.                OFFSET_CURRENT:   Current position.
  559.  
  560.                OFFSET_END:       The end of the file.
  561.  
  562.  
  563. If you want to move the file cursor to the beginning of the
  564. file (pointing to the first byte) you set the offset position
  565. to "OFFSET_BEGINNING" and the position value to 0.
  566.  
  567. If you on the other hand want to move the file cursor to the
  568. end of the file you set the offset position to "OFFSET_END" and
  569. the position value to 0.
  570.  
  571. To move 10 bytes forward from the current position you set the
  572. offset position to "OFFSET_CURRENT" and the position value to
  573. 10. To move 10 bytes backwards you set the position value to
  574. -10.
  575.  
  576. Here are some simple examples on how to use the Seek() function:
  577.  
  578.   /* Move the file cursor to the end of the file:  */
  579.   Seek( my_file, 0, OFFSET_END );
  580.  
  581.   /* Move the file cursor to the beginning of the file:  */
  582.   Seek( my_file, 0, OFFSET_BEGINNING );
  583.  
  584.   /* Move the file cursor 10 bytes forward */
  585.   /* from the current position:            */
  586.   Seek( my_file, 10, OFFSET_CURRENT );
  587.  
  588.   /* Move the file cursor 10 bytes backwards */
  589.   /* from the current position:              */
  590.   Seek( my_file, -10, OFFSET_CURRENT );
  591.  
  592.  
  593. See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
  594.           Read(), UnLock(), Write()
  595.  
  596. ---------------------------------------------------------------
  597.  
  598.  
  599.  
  600. 2.3.5  CLOSE THE FILE
  601.  
  602. Once you have finished working with the file and do not want to
  603. use it any more you must "close" it. When you close a file will
  604. the file cursor be removed, and other programs can now start to
  605. use the file.
  606.  
  607. Note that if you opened the file with a "shared lock" (only
  608. "write lock") other programs have been able to read the file
  609. but have not been able to modify it. If you opened the file
  610. with an "exclusive lock" ("read and write lock") no other
  611. programs have been able to read it nor to modify it.
  612.  
  613. Since other programs are "locked out" when you open a file it
  614. is very important that you close the file later on when you do
  615. not need it so other programs can use the file. Note that every
  616. file you have opened must be closed!
  617.  
  618.   *********************************************************
  619.   *                                                       *
  620.   *  REMEMBER! Every file you have opened MUST be closed  *
  621.   *  when you do not need it any more!                    *
  622.   *                                                       *
  623.   *********************************************************
  624.  
  625. It is very important that you close all files you have opened,
  626. and this must of course also be done if your program discovers
  627. an error and terminates. Sadly many programmers forget to
  628. clean up after themself if their program has to terminate
  629. because of an error. Please be careful with this!
  630.  
  631. To close a file you should use the "Close()" function which is
  632. defined like this:
  633.  
  634. ---------------------------------------------------------------
  635.  
  636. Close()
  637.  
  638. ROM library: "dos.library/Close", (All Versions)
  639. #include <clib/dos_protos.h>
  640.  
  641. Closes a previously opened file.
  642.  
  643. Synopsis: ok = Close( file );
  644.  
  645.   ok:     (LONG) If the file could successfully be saved TRUE
  646.           is returned. On the other hand, if there was some
  647.           sort of problem FALSE is returned.
  648.           
  649.           Even if the file could not be closed successfully
  650.           will the file cursor and all memory which have
  651.           previously been allocated internally now been
  652.           removed and deallocated. So even if you could not
  653.           close the file successfully you should NOT try to
  654.           close it again (that would crash the system)!
  655.           
  656.           If the file could not be closed there is actually
  657.           very little we can do about it. We might want to
  658.           resave some data (in another file) if we are afraid
  659.           the data otherwise might be lost, but we can not
  660.           do anything about the actual error. Just remember
  661.           that you must not try to close the file again, nor
  662.           to use it any more!
  663.  
  664.           On the old systems prior to Release 2 (older than
  665.           V36) the Close() do not return anything.
  666.  
  667.   file:   (BPTR) A BCPL pointer to an already open file which
  668.           should now be cosed.
  669.  
  670. Remember to close ALL files you have opened!
  671.  
  672. Here is a simple example on how to use the Close() function:
  673.  
  674.   - - -
  675.  
  676.   /* Close the file: */
  677.   if( Close( my_file ) )
  678.     printf( "File closed!\n" );
  679.   else
  680.     printf( "Error! File could not be closed!\n" );
  681.  
  682.   /* Remember that even if the file could not be */
  683.   /* closed we must NOT try to close it again!   */
  684.  
  685.  
  686. See also: IoErr(), Lock(), Open(), OpenFromLock(), Read(),
  687.           Seek(), UnLock(), Write()
  688.  
  689. ---------------------------------------------------------------
  690.  
  691.  
  692.  
  693. 2.4  FILES AND MULTITASKING
  694.  
  695. Since the Amiga can have several programs running at the same
  696. time it can happen that several programs work with the same
  697. file. This can be very dangerous since two programs may work
  698. simultaneously with one file. What one program creats may be
  699. destroyed by the other program, and this type of problem is
  700. ften called "the lost update problem". 
  701.  
  702.  
  703.  
  704. 2.4.1  THE LOST UPDATE PROBLEM
  705.  
  706. Imagine that you have two programs which are used alter some
  707. values in a file. Program "A" should multiply the values by 2.
  708. When "A" has updated the values program "B" should add 3.
  709.  
  710. If you look at the picture "LostUpdate.pic" you will see what
  711. can happen if you are very unlucky. Program "A" reads the value
  712. 10 and starts to calculate the answer. While "A" is busy
  713. working with the number program "B" starts and also reads the
  714. value before "A" has updated it! Program "B" will therefore
  715. also get the value 10.
  716.  
  717. Program "A" has now finished its calculations and writes the
  718. updated value 20 to the file. The program "B" finish its
  719. calculation and stores the value 13. As you can see has the
  720. update program "A" made been lost! This is why this type of
  721. error is called "the lost update problem".
  722.  
  723.  
  724.  
  725. 2.4.2  SOLVE THE LOST UPDATE PROBLEM
  726.  
  727. This type of problems with lost updates can luckily be avoided
  728. if the programs are "locking" the files. When a program "locks"
  729. a file no other program can use the file until the file has
  730. been unlocked. Whenever you are writing programs that may
  731. alter data in files other programs also work with you should be
  732. very careful to lock the files when necessary.
  733.  
  734. If the programs as described had locked the file while they
  735. were using it there would never have been any problems. See
  736. pricture "UpdateOK.pic". The first thing program "A" does is
  737. this time to lock the file. Program "A" can then read any
  738. values and do its calculation with them, and can be absolute
  739. sure that no other program can use the file.
  740.  
  741. Program "B" is maybe trying to read the file, but will not be
  742. able to open it, so it has to wait. Once "A" has finished the
  743. calculations it writes the new value to the file and then
  744. unlocks the file. Prgram "B" can now open the file a and locks
  745. it to prevent other programs to use the file. Program "B" does
  746. its calculations and then stores the new value in the file, and
  747. the file is unlocked.
  748.  
  749. Since the programs were locking the file while they were using
  750. it there were no values lost. The problem with the lost update
  751. has been solved.
  752.  
  753.  
  754.  
  755. 2.4.3  WHEN FILES SHOULD BE LOCKED
  756.  
  757. On large mainframe computers there exist many different types
  758. of locks with different priorities, but on the Amiga there
  759. exist only two different types of locks. You can lock a file
  760. so other programs may read it but not change it ("shared
  761. lock"), or if you do not want any other tasks to even read the
  762. file you set an "excluseive lock".
  763.  
  764. When you open a file with help of the Open() function you will
  765. automatically get a lock on the file. If you opened the file
  766. as a "new file" (MODE_NEWFILE) you will get an exclusive lock,
  767. and no other programs will be able to use the file until you
  768. close it.
  769.  
  770. However, if you have opened an "old" file (MODE_OLDFILE) or
  771. used the secial "read/write" option (MODE_READWRITE) the file
  772. will get a "shared lock". Other programs may therefore also
  773. read the file while you are working with it. (Whenever you
  774. save some data in the file it will temporarily be exclusive
  775. locked, but that will be converted into a normal shared lock
  776. as soon as all data has been witten.)
  777.  
  778. When you have opened a new file you will not need to lock the
  779. file yourself since it is already exclusive locked. If you
  780. have, on the other hand, opened an old file or used the read/
  781. write mode you might need to lock the file to prevent other
  782. programs to read it while you are working with it.
  783.  
  784. The only problem is actually when you should lock a file and
  785. when not. A wordprocessors that works with a document usually
  786. never locks the actual dockument. Normally the wordprocessor 
  787. even closes the file after it has read it, and opens it only
  788. temporarily while it saves the document. The file will
  789. therefore be completely "unlocked" while the wordprocessors
  790. is running!
  791.  
  792. If this is good or not can be discussed:
  793.  
  794.   (+) The advantage is that the file can be deleted or altered
  795.       by other programs while the wordprocessors is still
  796.       running. The user is free to do what he or she wants with
  797.       the file while the wordprocessors is running.
  798.  
  799.   (-) The disadvantage is that the user can do whatever he/she
  800.       likes with the file (some thinks this is an advantage as
  801.       described above).
  802.       
  803.       For example: A user is editing a document and while the
  804.       wordprocessor is running he/she tries to start a program
  805.       that alters the file (the user is maybe using an extrnal
  806.       spell checker, or  some type of "reformatting" program)
  807.       he/she will be allowed to do that. The problem comes if
  808.       the user then (after he/she has spellchecked and
  809.       reformatted the file) saves the document in the
  810.       wordprocessors. All alterations which were done to the
  811.       file will then be lost as described before!
  812.       
  813.  
  814. Personally I believe that most programs should keep at least a
  815. shared lock on the file while the program is using it. The
  816. external spell checker as described would in this case still be
  817. able to read the file (some freedom for the user), but when the
  818. spelchecker tries to save the data it will fail and the user is
  819. alerted and forced to create a new file for the spell checked
  820. data. 
  821.  
  822. One possible solution would be that the wordprocessors alerts
  823. the user whenever a file is going to be over written. In this
  824. case the user would also be warned that data might be lost. 
  825. However, one problem remains. What would happen if the user
  826. deletes the file (a copy of it is in the wordprocessor the user
  827. thinks so it does not matter...) and then suddenly there is
  828. power cut?
  829.  
  830. There exist a simple "rule" of when you should use an exclusive
  831. lock on a file and when you can use a shared lock:
  832.  
  833.   When files are altered automatically (without any action from
  834.   the user) you should keep an exclusive lock on the file if
  835.   possible. Automatic functions can very easily create
  836.   unexpected situations and updated data might be lost (as
  837.   described in our examle with the two programs "A" and "B").
  838.  
  839.   When files are altered because of some action from the user
  840.   it might be enough with a shared lock (if necesary). This
  841.   depends of course on how much you trust the user (another
  842.   "programming rule" is that you should never trust the user,
  843.   and in such case you should actually use an exclusive lock).
  844.  
  845.  
  846.  
  847. 2.4.4  LOCK FILES
  848.  
  849. When you want to put a lock on a file you should use the
  850. "Lock()" function. When you are working with files you actually
  851. only need to use this function when you want to add an
  852. exclusive lock to a file. At least a shared lock will have
  853. automatically been added for you when you opened the file (if
  854. you open a new file you will even get an exclusive lock).
  855.  
  856. This Lock() function is, however, also needed when you are
  857. working with some special file functions which will be
  858. descrbed in the following chapters.
  859.  
  860. The Lock() function is defined like this:
  861.  
  862. ---------------------------------------------------------------
  863.  
  864. Lock()
  865.  
  866. ROM library: "dos.library/Lock", (All Versions)
  867. #include <clib/dos_protos.h>
  868.  
  869. Puts a shared or excusive lock on an object (e.g. file).
  870.  
  871. Synopsis:    lock = Lock( file_name, mode );
  872.  
  873.   lock:      (BPTR) If the file could be locked a BPTR (BPCL
  874.              pointer) is returned. If the file on the other
  875.              hand could not be locked NULL is returned.
  876.              Possible reasons why the lock failed:
  877.              
  878.                1. The file simply does not exist.
  879.  
  880.                2. Some other program has an exclusive lock on
  881.                   the file, and consequntly no others may lock
  882.                   it (both shared and exclusive lock requests
  883.                   will fail).
  884.  
  885.                3. Som other program has a shared lock on the
  886.                   file but you wanted an exclusive lock. (If
  887.                   the file has a shared lock on it, and you
  888.                   tries to add another shared lock on it there
  889.                   will not be any problems.)
  890.  
  891.   file_name: (STRPTR) Pointer to a text string which contains
  892.              the name of the file you want to lock. If the file
  893.              is not located in the current directory you have
  894.              to include the necessary path.
  895.  
  896.   mode:      (LONG) On the Amiga there exist two types of
  897.              locks: (The flags are defined in header file
  898.              "dos/dos.h")
  899.  
  900.                SHARED_LOCK:     Other programs may read data in
  901.                                 the file, but no one else may
  902.                                 alter the file. (You can also
  903.                                 use the flag "ACCESS_READ"
  904.                                 which does the same thing.)
  905.              
  906.                EXCLUSIVE_LOCK:  No other programs may use this
  907.                                 file. (You can also use the
  908.                                 flag "ACCESS_WRITE" which does
  909.                                 the same thing.)
  910.  
  911.  
  912. Here is a simple example on how to use the Lock() function:
  913.  
  914.   /* A "BCPL" pointer to our lock: */
  915.   BPTR my_lock;
  916.  
  917.   - - -
  918.  
  919.   /* Try to lock the file with an exclusive lock: */
  920.   my_lock = Lock( "Highscore.dat", EXCLUSIVE_LOCK );
  921.  
  922.   /* Check if we have successfully locked the file or not: */
  923.   if( my_lock == NULL )
  924.     printf( "Could not lock the file!\n" );
  925.  
  926.  
  927. See also: Close(), IoErr(), Open(), OpenFromLock(), Read(),
  928.           Seek(), UnLock(), Write()
  929.  
  930. ---------------------------------------------------------------
  931.  
  932.  
  933.  
  934. 2.4.5  UNLOCK FILES
  935.  
  936. Whenever you do not need a lock on a file you must unlock it.
  937.  
  938.   ***********************************************************
  939.   *                                                         *
  940.   *  REMEMBER! Every file you have locked MUST be unlocked  *
  941.   *  when you do not need the lock any more!                *
  942.   *                                                         *
  943.   ***********************************************************
  944.  
  945. To unlock a file simply call the "UnLock()" function and give
  946. it the lock that should be unlocked. The UnLock() function is
  947. defined like this:
  948.  
  949. ---------------------------------------------------------------
  950.  
  951. UnLock()
  952.  
  953. ROM library: "dos.library/UnLock", (All Versions)
  954. #include <clib/dos_protos.h>
  955.  
  956. Unlocks a previously locked object (e.g. file).
  957.  
  958. Synopsis: UnLock( lock );
  959.  
  960.   lock:   (BPTR) A BPCL pointer to a lock that should be
  961.           unlocked. Remember that every file that you have
  962.           locked must be unlocked when you do not need the
  963.           look any more!
  964.  
  965. Here is a simple example on how to use the UnLock() function:
  966.  
  967.   - - -
  968.  
  969.   /* Unlock the file: */
  970.   UnLock( my_lock );
  971.  
  972.  
  973. See also: Close(), IoErr(), Lock(), Open(), OpenFromLock(),
  974.           Read(), Seek(), Write()
  975.  
  976. ---------------------------------------------------------------
  977.  
  978.  
  979.  
  980. 2.4.6  OPEN A LOCKED FILE
  981.  
  982. If you have open a file and want to put an exclusive lock on it
  983. the Lock() function will fail. The reason why it will fail is
  984. because the file is currently used by someone (in this case
  985. yourself since you have opened the file), and you can therefore
  986. not put an exclusive lock on the file. The problem is that you
  987. can not do the opposit eiter, you can not lock a file
  988. exclusively and then try open it since the Open() function will
  989. then fail.
  990.  
  991. Now it seems like it would be impossible to use an old file and
  992. still be able to put an exclusive lock on it. (New files will
  993. automaticaly get an exclusive lock.) The fact is that prior to
  994. Release 2 it was impossible (unless you did some low level
  995. work). However, with Release 2 a new open function,
  996. "OpenFromLock()", was introduced. If the user has dos version
  997. 36 or higher you can lock the file (exclusive or shared,
  998. although shared is unnecessary since that is done automatically
  999. when you open the file) and then use this new function to open
  1000. the file with help of the lock.
  1001.  
  1002. Please remember to check that the user really have dos library
  1003. V36 or higher before you try to call the OpenFromLock()
  1004. function!
  1005.  
  1006. The OpenFromLock() function is defined like this:
  1007.  
  1008. ---------------------------------------------------------------
  1009.  
  1010. OpenFromLock()
  1011.  
  1012. ROM library: "dos.library/OpenFromLock", (V36+)
  1013. #include <clib/dos_protos.h>
  1014.  
  1015. Opens an already locked file.
  1016.  
  1017. Synopsis:  my_file = OpenFromLock( lock );
  1018.  
  1019.   my_file: (BPTR) If the file could be opened a BPTR (BPCL
  1020.            pointer) is returned. If the file on the other hand
  1021.            could not be opened NULL is returned.
  1022.  
  1023.   lock:    (BPTR) A BPCL pointer to a lock which file should be
  1024.            opened. You must of course have locked the file
  1025.            successfully before you may open the file with it!
  1026.  
  1027. Here is a simple example on how to use the OpenFromLock()
  1028. function:
  1029.  
  1030.   /* A "BCPL" pointer to our lock: */
  1031.   BPTR my_lock;
  1032.  
  1033.   /* A "BCPL" pointer to our file: */
  1034.   BPTR my_file;
  1035.  
  1036.   - - -
  1037.  
  1038.   /* Put an exclusive lock on an existing file: */
  1039.   my_lock = Lock( "RAM:HighScore.dat", EXCLUSIVE_LOCK );
  1040.  
  1041.   /* Could we lock the file successfully? */
  1042.   if( !my_lock )
  1043.   {
  1044.     /* Problems! Inform the user: */
  1045.     printf( "Could not put an exclusive lock on the file!\n" );
  1046.  
  1047.     /* Exit with an error code: */
  1048.     exit( 20 );
  1049.   }
  1050.  
  1051.  
  1052.   /* We will now try to open the file with help */
  1053.   /* of the lock we already have:               */
  1054.   my_file = OpenFromLock( my_lock );
  1055.   
  1056.   /* Have we opened the file successfully? */
  1057.   if( !my_file )
  1058.   {
  1059.     /* Problems! Inform the user: */
  1060.     printf( "Error! Could not open the file!\n" );
  1061.  
  1062.     /* Unlock the file: */
  1063.     UnLock( my_lock );
  1064.  
  1065.     /* Exit with an error code: */
  1066.     exit( 21 );
  1067.   }
  1068.  
  1069.   - - -
  1070.  
  1071.   /* Close the file: */
  1072.   Close( my_file );
  1073.  
  1074.   /* Unlock the file: */
  1075.   UnLock( my_lock );
  1076.  
  1077.  
  1078. See also: Close(), IoErr(), Lock(), Open(), Read(), Seek(),
  1079.           UnLock(), Write()
  1080.  
  1081. ---------------------------------------------------------------
  1082.  
  1083.  
  1084.  
  1085. 2.5  OTHER FILE FUNCTIONS
  1086.  
  1087. Up to now we have discussed the elementary parts on how to work
  1088. with files. We have looked at how to open, work with and close
  1089. files, as well as how to use any necessary locks. This is
  1090. enough for small applications, but you might need to do more
  1091. things with the files. There exist a lot of useful support
  1092. functions which will be described in the next chapter "File
  1093. Functions".
  1094.  
  1095.  
  1096.